module Dot where

import Data.Graph.Inductive.Graph (Node, Edge, Graph, edges, nodes, lab, mkGraph, LNode, LEdge, UNode)
import Data.Graph.Inductive.Tree (UGr)
import Utils (addToSet, cutStrByCh, cutStrByChToInt)

showGraphInDot :: (Graph gr, Show a) => gr a b -> [Node] -> String
showGraphInDot graph list = "graph G {\n" ++  nodesRepr ++ edgesRepr ++ "}" 
    where  
    edgesRepr =  concat [ showEdge e | e@(f,t) <- edges graph, f <= t ]
    nodesRepr =  concat [ showNode n | n <- nodes graph ]  
    showEdge (f,t) = concat [show f, " -- ", show t, "; \n" ]  
    showNode n     = concat [(show n ++) $  showLabel, ";\n" ] 
        where
        showLabel | n `elem` list = "[label=\"in independent set\"]"
                  | otherwise     = concat ["[label=",show n,"]"]

getGraph :: String -> UGr
getGraph str =
        case lines str of
        hd:text ->
            case words hd of
            ["graph",_,"{"] ->
                  case getEdges of 
                  (nds,edgs) -> mkGraph nds edgs
            _ -> error $ concat["Invalid header\n", hd]
            where	
            getEdges :: ([LNode ()],[LEdge ()])
            getEdges = foldl parseL ([],[]) text 
                where
                parseL v@(nds,edgs) line = 
                    case words line of
                      begin:"--":end:t -> 
                               (addToSet nds (beginVal ,()) `addToSet` (endVal ,()) , 
                                       addToSet edgs (beginVal ,endVal ,()) `addToSet` (endVal , beginVal,())) 
                                where	
                                beginVal = read begin
                                endVal = cutStrByChToInt end ';' 
                      ["}"]   -> v   
                      []      -> v
                      begin:t | cutStrByCh begin '-' /= begin -> (addToSet nds (beginVal ,()) `addToSet` (endVal ,()) , 
                                                             addToSet edgs (beginVal ,endVal ,()) `addToSet` (endVal , beginVal,()))                                                          
                              | cutStrByCh begin ';' /= begin -> add
                              | t == [";"] -> add
                              | otherwise -> error $ "Invalid dot file: line is wrong "
                                     where                                     
                                     beg = cutStrByChToInt begin ';'	
                                     beginVal = cutStrByChToInt begin '-'
                                     endVal = cutStrByChToInt 
                                                 (dropWhile (== '-')  (dropWhile (/= '-') begin)) ';'  
                                     add = (addToSet nds (beg,()),edgs)                                                                                                                                   
        _ -> error $ "Invalid dot file " 
